package khiem.android.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Random;

import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class HangMan extends Activity implements OnClickListener {
  
  private final int MAX_GUESSES = 6;
  
  private TextView wordLabel;
  private TextView wrongLabel;
  private ImageView image;
  
  private Dialog dialog;
  
  private char[] word;
  private int misses;
  private char[] visibleWord;
  private StringBuilder wrongWord;
  
  private ArrayList<String> dictionary; 
  
  /**
   * Ids for all dialog windows
   */
  static final int DIALOG_ABC_ID = 1;
  static final int DIALOG_DEF_ID = 2;
  static final int DIALOG_GHI_ID = 3;
  static final int DIALOG_JKL_ID = 4;
  static final int DIALOG_MNO_ID = 5;
  static final int DIALOG_PQR_ID = 6;
  static final int DIALOG_STU_ID = 7;
  static final int DIALOG_VWX_ID = 8;
  static final int DIALOG_YZ_ID = 9;
  static final int DIALOG_WIN_ID = 10;
  static final int DIALOG_LOSE_ID = 11;
  
  private static final char[][] dialogKeypadTable = new char[12][4];
  private int currentDialogId;
  
  static {
    char c = 'A';
    for (int i = 1; i <= 11; i++)
      for (int j = 1; j <= 3; j++) {
        dialogKeypadTable[i][j] = c;
        c++;
      }
  }

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    wordLabel = (TextView) this.findViewById(R.id.word);
    wrongLabel = (TextView) this.findViewById(R.id.wrong_guesses);
    image = (ImageView) this.findViewById(R.id.image);
    
    loadDictionary();
    setClickListener();
    startGame();
  }
  
  public void startGame() {
    initWord();
    image.setImageResource(R.drawable.hm1);
    misses = 0;
  }
  
  private void guess(char letter) {
    boolean badGuess = true;
    boolean wordFinished = true;
    
    if (dialog != null) {
      dialog.dismiss();
      removeDialog(currentDialogId);
    }
    
    //check for matches for this letter
    for( int i = 0; i < word.length; i++ ) {
      if( word[i] == letter ) {
        visibleWord[2*i] = letter;
        badGuess = false;
      }
      else if(visibleWord[2*i]=='_') {
        wordFinished = false;
      }
    }
    
    wordLabel.setText( new String(visibleWord) );
    if(wordFinished) {
      // show wining dialog
      showDialog(DIALOG_WIN_ID);
      //startGame();
    }
    else if (badGuess) {
      misses++;
      wrongWord.append(letter + " ");
      wrongLabel.setText(wrongWord.toString());
      // set image
      updateImg();
      if(misses == MAX_GUESSES) {
        // show losing dialog
        showDialog(DIALOG_LOSE_ID);
        //startGame();
      }
    }
    
  }
  
  private void updateImg() {
    switch (misses) {
    case 0: 
      image.setImageResource(R.drawable.hm1);
      break;
    case 1:
      image.setImageResource(R.drawable.hm2);
      break;
    case 2: 
      image.setImageResource(R.drawable.hm3);
      break;
    case 3:
      image.setImageResource(R.drawable.hm4);
      break;
    case 4:
      image.setImageResource(R.drawable.hm5);
      break;
    case 5:
      image.setImageResource(R.drawable.hm6);
      break;
    case 6: 
      image.setImageResource(R.drawable.hm7);
    }
  }
  
  
  private void initWord() {
    String newWord = getRandomWord();
    if (newWord == null) newWord = "empty";
    word = newWord.toUpperCase().toCharArray();
    visibleWord = new char[2*word.length];
    for (int i = 0; i < word.length; i++){
      if (word[i] != ' ')
        visibleWord[2*i]='_';
      else
        visibleWord[2*i]=' ';
      visibleWord[2*i+1] = ' ';
    }
    wrongWord = new StringBuilder();
    
    wordLabel.setText(new String(visibleWord));
    wrongLabel.setText("");
  }

  /* (non-Javadoc)
   * @see android.view.View.OnClickListener#onClick(android.view.View)
   */
  @Override
  public void onClick(View v) {
    switch(v.getId()) {
    case R.id.abc_button:
      showDialog(DIALOG_ABC_ID);
      break;
    case R.id.def_button:
      showDialog(DIALOG_DEF_ID);
      break;
    case R.id.ghi_button:
      showDialog(DIALOG_GHI_ID);
      break;
    case R.id.jkl_button:
      showDialog(DIALOG_JKL_ID);
      break;
    case R.id.mno_button:
      showDialog(DIALOG_MNO_ID);
      break;
    case R.id.pqr_button:
      showDialog(DIALOG_PQR_ID);
      break;
    case R.id.stu_button:
      showDialog(DIALOG_STU_ID);
      break;
    case R.id.vwx_button:
      showDialog(DIALOG_VWX_ID);
      break;
    case R.id.yz_button:
      showDialog(DIALOG_YZ_ID);
      break;
    
    // keypressed in dialog now
    case R.id.button1:
      guess(dialogKeypadTable[currentDialogId][1]);
      break;
    case R.id.button2:
      guess(dialogKeypadTable[currentDialogId][2]);
      break;
    case R.id.button3:
      guess(dialogKeypadTable[currentDialogId][3]);
      break;
    case R.id.newGame:
      dialog.dismiss();
      removeDialog(currentDialogId);
      startGame();
      break;
    case R.id.quitGame:
      finish();
      break;
    }
  }
  
  @Override
  protected Dialog onCreateDialog(int id) {
    Button key1;
    Button key2;
    Button key3;
    currentDialogId = id;
    if (id <= 9 && id >= 1) {
      dialog = new Dialog(this);
      dialog.setContentView(R.layout.keypad);
      dialog.setTitle("Select a letter");
      key1 = (Button) dialog.findViewById(R.id.button1);
      key2 = (Button) dialog.findViewById(R.id.button2);
      key3 = (Button) dialog.findViewById(R.id.button3);
      
      key1.setText(String.valueOf(dialogKeypadTable[id][1]));
      key2.setText(String.valueOf(dialogKeypadTable[id][2]));
      
      key1.setOnClickListener(this);
      key2.setOnClickListener(this);
      
      if (id != 9) {
        key3.setText(String.valueOf(dialogKeypadTable[id][3]));
        key3.setOnClickListener(this);
      } else key3.setVisibility(View.INVISIBLE);
      
    } else {
      dialog = new Dialog(this);
      dialog.setContentView(R.layout.endgame);
      TextView message = (TextView) dialog.findViewById(R.id.endMessage);
      if (id == DIALOG_WIN_ID) message.setText("Congratulations, you got the answer!");
      if (id == DIALOG_LOSE_ID) message.setText("You ran out of guesses! The answer is "+ new String(word));
      Button newGame = (Button) dialog.findViewById(R.id.newGame);
      Button quitGame = (Button) dialog.findViewById(R.id.quitGame);
      newGame.setOnClickListener(this);
      quitGame.setOnClickListener(this);
    }
    return dialog;
  }
  
  /**
   * Binds observer to all buttons
   */
  private void setClickListener() {
    Button abc = (Button) this.findViewById(R.id.abc_button);
    abc.setOnClickListener(this);
    Button def = (Button) this.findViewById(R.id.def_button);
    def.setOnClickListener(this);
    Button ghi = (Button) this.findViewById(R.id.ghi_button);
    ghi.setOnClickListener(this);
    Button jkl = (Button) this.findViewById(R.id.jkl_button);
    jkl.setOnClickListener(this);
    Button mno = (Button) this.findViewById(R.id.mno_button);
    mno.setOnClickListener(this);
    Button pqr = (Button) this.findViewById(R.id.pqr_button);
    pqr.setOnClickListener(this);
    Button stu = (Button) this.findViewById(R.id.stu_button);
    stu.setOnClickListener(this);
    Button vwx = (Button) this.findViewById(R.id.vwx_button);
    vwx.setOnClickListener(this);
    Button yz = (Button) this.findViewById(R.id.yz_button);
    yz.setOnClickListener(this);
    
  }
  
  /**
   * Loads dictionary from resource file
   */
  private void loadDictionary() {
    dictionary = new ArrayList<String>();
    InputStreamReader isr = new InputStreamReader(getResources().openRawResource(R.raw.dictionary));
    BufferedReader reader = new BufferedReader(isr);
    String line;
    try {
      while ((line = reader.readLine()) != null) {
        dictionary.add(line);
      }
    } catch (IOException e) {
      // log here
      Log.w("HangMan", "Exception occurs when reading dictionary resource file");
    } finally {
      try {
        reader.close();
      } catch (IOException e) {
        // log, and swallow
        Log.d("HangMan", "Exception occurs when closing connection to resource file");
      }
    }
  }
  
  private String getRandomWord() {
    if (dictionary == null || dictionary.size() < 1) return null; 
    int size = dictionary.size();
    Random rand = new Random();
    return dictionary.get(rand.nextInt(size));
  }
}
  
